if(!window["vg"]) {
	window["vg"] = {};
}
if(!vg.visualization) {
	vg.visualization = {};
}

vg.visualization.MultipleSelectionList = (function () {
	var classObject = {
		gridHeader : "groupheader",
		elementBar : "elementbar",
		paginationBar : "paginationbar",
		disabledPaginationBtn : "title4 disabled",
		enabledPaginationBtn : "title4",
		xOnMouseOut : "title4",
		xOnMouseOver : "highlighthover",
		table : "grid navigational",
		oddRow : "oddrow",
		evenRow : "evenrow",
		selected : "highlight",
		th : "_tableHeader",
		td : "_tableColumn",
		input : "_tableInput",
		container : "_tableContainer",
		tableBtn : "_tableBtn"
	};

	var paginationObj = {
		idSuffix : "_nav{btn}",
		spanClass : "runtimeSpriteImg",
		inactiveBgPos : {
			first : "-12px 0px",
			previous : "-12px -12px",
			next : "-12px -24px",
			last : "-12px -36px"
		}
	};
	
	//Init tasks
	var style = ".grid.navigational ._tableHeader{text-align:center;}\
				 .grid.navigational ._tableHeader, .grid.navigational tbody ._tableColumn{padding:0px 2px;border:1px solid #b6e4f3;}\
				 .grid td ._tableInput, .grid th ._tableInput {width:100%;whiteSpace:nowrap;overflow:hidden;textOverflow:ellipsis;border:0px}\
				 .grid th ._tableInput{color:#0C5BAA;font-weight:bold} \
				 ._tableContainer{border : 1px solid #5CAAEA; padding : 1px; background-color : white;} \
				 ._tableContainer ._tableBtn{font-weight : normal, cursor : default, float : right}";
    var styleElmt = document.createElement("style");
    styleElmt.setAttribute("type", "text/css");
    if (styleElmt.styleSheet) { //for IE
		styleElmt.styleSheet.cssText = style;
	} else { //the world
		styleElmt.innerHTML = style;
	}
    document.getElementsByTagName("head")[0].appendChild(styleElmt);		
	
	var List = function (inputObj) {
		this.container = (inputObj.container.constructor == String ? document.getElementById(inputObj.container) : inputObj.container);
		this.container.innerHTML = "";
		this.listName = inputObj.listName;
		this.headers = inputObj.headers;
		this.idFields = {};
		for (var i = this.headers.length - 1; i >= 0; i--) {
			this.headers[i].isIdentifying && (this.idFields[this.headers[i]["dataName"]] = true);
		}
		this.numRows = inputObj.numRows;
		this.paginationVisible = inputObj.pagination || true;
		this.checkBoxWidth = inputObj.checkBoxWidth || "21px";
		this.rowHeight = inputObj.rowHeight || "23px";
		this.data = [];
		this.dataCache = {};
		drawList(this);
		this.events = {};
		this.currentPageNumber = 1;
		drawTable(this);
		this.viewHeight = calculateViewHeight(this);
	};
	
	var createTag = function(type, config){
        var tag = document.createElement(type);
        if (config) {
            config.id && (tag.id = (config.id));
            config.className && (tag.className = config.className);
            for (var i in config.style) {
				tag.style[i] = config.style[i];
			}
			for (i in config.attributes) {
				tag.setAttribute(i, config.attributes[i]);
			}
			if(type != "input" && type != "table") {	//for IE.... Obviously..
				tag.innerHTML = config.innerHTML ? config.innerHTML : "";
			}
            config.parent && config.parent.appendChild(tag);			
        }
        return tag;
    };
	
	var removePx = function (str) {
		return Number(str.replace("px", ""));
	};
	
	var drawList = function (listObj) {
		listObj.containerDiv = createTag("div", {
		    className : classObject["container"],
			parent : listObj.container
		});
		listObj.headerDiv = createTag("div", {
			className : classObject.gridHeader,
			style : {
				border : "0",
				textAlign : "left"
			},
			parent : listObj.containerDiv
		});
		listObj.headerLabel = createTag("label", {
			innerHTML : listObj.listName,
			parent : listObj.headerDiv
		});
		listObj.elementBar = createTag("div", {
			className : classObject.elementBar,
			parent : listObj.containerDiv
		});
		listObj.paginationBar = createTag("span", {
			className : classObject.paginationBar,
			parent : listObj.elementBar
		});
		var button = createTag("button", {
			style : {
				fontWeight : "normal",
				width : "17px",
				cursor : "default"				
			},
			className : classObject.enabledPaginationBtn
		});
		var p = createTag("p", {
			style : {
				width : "17px"	
			},
			attributes : {
				align : "left",
				xclassName : "title4",
				xonmouseout : "this.className='" + classObject.xOnMouseOut + "'",
				xonmouseover : "this.className='" + classObject.xOnMouseOver + "'"			
			},
			parent : button
		});
		var span = createTag("span", {
			className : paginationObj.spanClass,
			style : {
				marginLeft : "1px"
			},
			parent : p
		});
		listObj.firstButton = createPaginationBtn(button, listObj, "first", first);
		listObj.previousButton = createPaginationBtn(button, listObj, "previous", previous);
		listObj.nextButton = createPaginationBtn(button, listObj, "next", next);
		listObj.lastButton = createPaginationBtn(button, listObj, "last", last);
	};
	
	var attachHandler = function (element, handler, eventName, listObj, args) {
		element[eventName] = function (eventObject) {
			args = args || [];
			args.push(eventObject);
			handler.apply(listObj, args);
		};
	};
	
	var drawTable = function (listObj) {
		listObj.headerTable = createTag("table", {
			className : classObject.table,
			parent : listObj.containerDiv
		});
		var headerThead = createTag("thead", {
			parent : listObj.headerTable
		});
		var checkAllTh = createTag("th", {
			style : {
				width : listObj.checkBoxWidth
			},
			parent : headerThead,
			className : classObject.th
		});

		listObj.checkAll = createCheckBox(listObj.listName + "_checkAll", checkAllTh);
		var tableWidth = removePx(listObj.checkBoxWidth);
		attachHandler(listObj.checkAll, checkAllHandler, "onchange", listObj);
		listObj.tableDiv = createTag("div", {
			style : {
				overflow : "hidden"
			},
			parent : listObj.containerDiv
		});
		listObj.dataTable = createTag("table", {
			className : classObject.table,
			parent : listObj.tableDiv
		});
		//adding headers
		for(var i = 0; i < listObj.headers.length; i++) {
			if(!listObj.headers[i]["isHidden"]) {
				var header = createTag("th", {
					style : {
						width : listObj.headers[i].width,
						height: listObj.rowHeight,
						lineHeight: listObj.rowHeight
					},
					parent : headerThead,
					className : classObject.th
				});
				createTag("input", {
					parent: header,
					className : classObject.input,
					attributes: {
						readonly : "true",
						value: listObj.headers[i].displayName
					}
				});					
				tableWidth += removePx(listObj.headers[i].width);				
			}
		}		
		listObj.tbody = createTag("tbody", {
			parent : listObj.dataTable
		});
		//Adding Rows
		//adding config for checkbox header
		listObj.headers.unshift({
			displayName : "_checkAll",
			width : listObj.checkBoxWidth,
			propertyName : "_checkAll"
		});
        for(i = 0; i < listObj.numRows; i++) {
			insertDataRow(i, listObj);
		}
		
		listObj.tableDiv.style.height = calculateViewHeight(listObj) + "px";
		listObj.headerTable.style.width = tableWidth + "px";
		listObj.dataTable.style.width = tableWidth + "px";
		listObj.containerDiv.style.width = tableWidth + "px";	
		listObj.buttonDiv = createTag("div", {
			style : {
				height : "23px",
				borderTop : "1px solid #B6E4F3"
			},
			parent : listObj.containerDiv
		});
		listObj.cancelBtn = createTag("button", {
		    className : classObject["tableBtn"],
			style : {
				width : "70px",
				marginTop : "3px"					
			},
			parent : listObj.buttonDiv,
			innerHTML : "Cancel"
		});
		attachHandler(listObj.cancelBtn, cancelBtnHandler, "onclick", listObj);
		listObj.okBtn = createTag("button", {
		    className : classObject["tableBtn"],
			style : {
				width : "50px",
				margin : "3px 3px 0px 0px"
			},
			parent : listObj.buttonDiv,
			innerHTML : "OK"
		});
		attachHandler(listObj.okBtn, okBtnHandler, "onclick", listObj, [false]);
		setButtons(listObj);
	};
	
	
	var calculateViewHeight = function (listObj) {
		var lastRowInView = listObj.dataTable.rows[listObj.numRows - 1];
		return Number(lastRowInView.offsetTop) + Number(lastRowInView.offsetHeight);
	};	
	
	var insertDataRow = function (index, listObj) {
		var row = createTag("tr", {
			className: ((index % 2 == 0) ? classObject.oddRow : classObject.evenRow),
			parent : listObj.tbody
		});
		for(var j = 0; j < listObj.headers.length; j++) {
			if(!listObj.headers[j]["isHidden"]) {
                var cell = createTag("td", {
                    parent: row,
					className: classObject.td,
                    style: {
                        height: listObj.rowHeight,
                        lineHeight: listObj.rowHeight,
                        width: listObj.headers[j].width
                    },
                    attributes: {
                        align: (j == 0 ? "center" : "left")
                    }
                });
				j != 0 && createTag("input", {
					parent: cell,
					className : classObject.input,
					attributes: {
						readonly : "true"
					}
				});							
			}
		}
	};
	
	var fillDataRow = function (row, listObj, data) {
		var dataObj = data[row.rowIndex];
		var dataCacheKey = "";
		for(var j = 1, c = 1; j < listObj.headers.length; j++) {
			var dataName = listObj.headers[j].dataName;
			if(!listObj.headers[j]["isHidden"]) {
				var input = row.cells[c++].childNodes[0];
				input.value = dataObj[dataName];
				input.setAttribute("title", dataObj[dataName]);				
			}
			listObj.idFields[dataName] && (dataCacheKey += dataObj[dataName] + ";");
		}
		dataCacheKey.length > 0 && (listObj.dataCache[dataCacheKey] = true);
	};
	
	var clearDataRow = function (row) {
		for(var i = 0; i < row.cells.length; i++) {
			if(i == 0) {
				row.cells[i].innerHTML = "";
			} else {
				row.cells[i].childNodes[0].value = "";
			}
		}
	};
	
	var createPaginationBtn = function (button, listObj, dir, handler) {
		var newButton = button.cloneNode(true);
		newButton.id = listObj.listName.replace(/\s/g, "") + paginationObj.idSuffix.replace("{btn}", dir);
		newButton.childNodes[0].childNodes[0].style.backgroundPosition = paginationObj.inactiveBgPos[dir];
		listObj.paginationBar.appendChild(newButton);
		attachHandler(newButton, handler, "onclick", listObj);
		return newButton;
	};
	
	/****************************** Handlers ************************************/
	var first = function () {
		triggerPaginationEvent.call(this, "beforefirst", 0);
		this.tableDiv.scrollTop = 0;
		this.currentPageNumber = 1;
		setButtons(this);
	};
	
	var last = function () {
		triggerPaginationEvent.call(this, "beforelast", this.data.length - 1);
		if(this.data.length <= this.numRows) {
			return;
		}
		var lastPageRow = this.dataTable.rows[this.data.length - this.numRows];
		this.tableDiv.scrollTop = Number(lastPageRow.offsetTop);
		this.currentPageNumber = this.totalPages;
		setButtons(this);
	};
	
	var next = function () {
		var lastDataIndex = this.numRows*this.currentPageNumber - 1;
		triggerPaginationEvent.call(this, "beforenext", lastDataIndex);
		if(this.currentPageNumber == this.totalPages) {
			return;
		}
		this.tableDiv.scrollTop = Number(this.tableDiv.scrollTop) + Number(this.viewHeight);
		this.currentPageNumber++;
		setButtons(this);
	};
	
	var previous = function () {
		var firstDataIndex = this.numRows*(this.currentPageNumber - 1) - 1;
		triggerPaginationEvent.call(this, "beforeprevious", firstDataIndex);
		if(this.currentPageNumber == 1) {
			return;
		}
		this.tableDiv.scrollTop = Number(this.tableDiv.scrollTop) - Number(this.viewHeight);
		this.currentPageNumber--;
		setButtons(this);
	};
	
	var triggerPaginationEvent = function(eventName, dataIndex) {
		this.events[eventName] && this.events[eventName]({
			data : this.data[dataIndex],
			index : dataIndex
		});
	};

	var setButtons = function(listObj) {
		var buttonStats = {
			firstButton : true,
			previousButton : true,
			nextButton : true,
			lastButton : true
		};

		if(listObj.currentPageNumber == 1) {
			buttonStats.firstButton = false;
			buttonStats.previousButton = false;
		} 
		if (listObj.data.length == 0 || listObj.currentPageNumber == listObj.totalPages) {
			buttonStats.nextButton = false;
			buttonStats.lastButton = false;			
		}
		for( var i in buttonStats) {
			setButtonView(listObj[i], buttonStats[i]);
		}
	};
	
	var setButtonView = function(button, isEnabled) {
		button.className = classObject[isEnabled ? "enabledPaginationBtn" : "disabledPaginationBtn"];
	};
	
	var checkAllHandler = function (avoidEvent) {
		for(var i = 0; i < this.data.length; i++) {
			this.data[i].checkBox.checked = this.checkAll.checked;
		}
		if(!avoidEvent && this.events["oncheckall"]) {
			this.events["oncheckall"]({
				checked : this.checkAll.checked,
				data : this.data
			});
		}		
	};
	
	var checkBoxHandler = function (eventObject) {
		var checkBox = eventObject.srcElement || eventObject.target;
		if(this.events["onrowchecked"]) {
			this.events["onrowchecked"]({
				checked : checkBox.checked,
				data : this.data[checkBox.id]
			});
		}
	};
	
	var okBtnHandler = function (keepMenu) {
		var eventObject = [];
		for(var i = 0; i < this.data.length; i++) {
			if(this.data[i].checkBox.checked) {
				eventObject.push(this.data[i]);
			}
		}
		!keepMenu && this.hideMenu();
		if(!keepMenu && this.events["onokclick"]) {
			this.events["onokclick"](eventObject);
		}
		return eventObject;
	};
	
	var cancelBtnHandler = function () {
		if(this.events["oncancelclick"]) {
			this.events["oncancelclick"]();
		}
	};
	
	var rowSingleClickHandler = function (eventObject, fromInside) {
		var row = eventObject.currentTarget;
		if(this.data.length < (row.rowIndex + 1)) {
			return;
		}	
		var rows = this.tbody.rows;
		for(var i = 0; i < rows.length; i++) {
			rows[i].classList.contains(classObject.selected) && rows[i].classList.toggle(classObject.selected);
		}
		row.classList.toggle(classObject.selected);
		!fromInside && this.events["onrowselect"] && this.events["onrowselect"]({
			row: row,
			data: this.data[row.rowIndex]
		});
	};
	
	var rowDoubleClickHandler = function (eventObject) {
		var row = eventObject.currentTarget;
		if(this.events["onrowdbclick"]) {
			this.events["onrowdbclick"]({
				row: row,
				data: this.data[row.rowIndex]
			});
		}		
	};	
	
	var setTableScroll = function (listObj, isScrollable) {
		if(isScrollable) {
			listObj.tableDiv.style.overflowX = "hidden";
			listObj.tableDiv.style.overflowY = "auto";
		} else {
			listObj.tableDiv.style.overflow = "hidden";			
		}		
	};
	
	/*
	 * IE outdoes itself - doesn't allow to add type property to input elements dynamically for so called
	 * security reasons
	 */
	var createCheckBox = function (id, parent) {
		var dummy = document.createElement("div");
		dummy.innerHTML = "<input type='checkbox' id='" + id + "'>";
		var checkBox = dummy.childNodes[0];
		parent.appendChild(checkBox);
		return checkBox;
	};
	
	var getDataCacheKey = function (dataObj, listObj) {
		var dataCacheKey = ""
		for (var i = listObj.headers.length - 1; i >= 0; i--) {
			var dataName = listObj.headers[i]["dataName"];
			if(listObj.idFields[dataName]) {
				dataCacheKey += dataObj[dataName] + ";";
			}
		};
		return dataCacheKey;
	}
	
	var copyData = function(data, listObj) {
		listObj.data = [];
		for(var i = 0; i < data.length; i++ ) {
			listObj.data[i] = {};
			for(var j in data[i]) {
				listObj.data[i][j] = data[i][j];
			}
		}
	};

	List.prototype = (function () {		
		var setData = function (data) {
			var currentDataLength = this.data.length;
			for(var i = 0; i < data.length; i++) {
				var pageNum = parseInt(i/this.numRows);
				if(pageNum > 0 && i > currentDataLength - 1) {
					insertDataRow(i, this);
				} 
				if (i > currentDataLength - 1) {
					data[i].checkBox = createCheckBox(i + "", this.dataTable.rows[i].cells[0]);			
					attachHandler(data[i].checkBox, checkBoxHandler, "onchange", this);
				} else {
					data[i].checkBox = this.data[i].checkBox;
				}
				fillDataRow(this.dataTable.rows[i], this, data);
				attachHandler(this.dataTable.rows[i], rowSingleClickHandler, "onclick", this);
				attachHandler(this.dataTable.rows[i], rowDoubleClickHandler, "ondblclick", this);
			}
			if(data.length < this.numRows) {
				for(var j = 0; j < (this.data.length - this.numRows); j++){
					this.dataTable.deleteRow(-1);
				}
				for(j = data.length; j < this.numRows; j++) {
					clearDataRow(this.dataTable.rows[j]);
				}
			}
			copyData(data, this);
			this.totalPages = Math.ceil(data.length/this.numRows);
			setButtons(this);
			if(this.checkAll.checked) {
				this.checkAll.checked = false;
				checkAllHandler.call(this, true);
			}
			this.setPaginationVisibility(this.paginationVisible);
			rowSingleClickHandler.call(this, {
				currentTarget: this.tbody.rows[0]
			}, true);
		};
								
		var setEventListener = function (eventName, handler) {
			this.events[eventName] = handler;
		};
		
		var hideMenu = function () {
			this.containerDiv.style.display = "none";
		};

		var showMenu = function () {
			this.containerDiv.style.display = "block";
		};
		
		var setButtonVisibility = function (isVisible) {
			var display = isVisible ? "block" : "none";
			this.okBtn.style.display = display;
			this.cancelBtn.style.display = display;
		};
		
		var getSelection = function () {
			return okBtnHandler.call(this, true);
		};
		
		var getData = function () {
			return this.data;
		};
		
		var setPaginationVisibility = function (isVisible) {
			var display = isVisible ? "block" : "none";
			this.paginationVisible = isVisible;
			this.elementBar.style.display = display;
			setTableScroll(this, this.data && this.data.length != 0 && !this.paginationVisible);
		};

		var appendData = function (extraData, position) {
			var dataCacheKey = ""
			for (var i = 0; i < extraData.length; i++) {
				var dataObj = extraData[i];
				var dataCacheKey = getDataCacheKey(dataObj, this);
				dataCacheKey.length > 0 && (this.dataCache[dataCacheKey] ? extraData.splice(i,1) : (this.dataCache[dataCacheKey] = true));
			};
			extraData.unshift(0);
			extraData.unshift(position);
			this.data.splice.apply(this.data, extraData);
			this.setData(this.data);
		};
				
		return {
			"setData" : setData,
			"setEventListener" : setEventListener,
			"hideMenu" : hideMenu,
			"showMenu" : showMenu,
			"setButtonVisibility" : setButtonVisibility,
			"getSelection" : getSelection,
			"getData" : getData,
			"setPaginationVisibility" : setPaginationVisibility,
			"appendData" : appendData
		};
	})();
	return List;
})();

scriptCallback && scriptCallback("Multiple Selection List");